%module(directors="1") pipeit
%include "pyabc.i"
%include "std_string.i"
%include "std_list.i"
%include "std_vector.i"
%include "std_pair.i"
%include "std_map.i"
%include "exception.i"
%include "cpointer.i"
%include "factory.i"

%rename(assign) *::operator=;

%exception {
  try {
    $action
  } catch (const gestface::gestface_exception& e) {
    SWIG_exception(SWIG_RuntimeError, e.what());
  } catch (const std::exception& e) {
    SWIG_exception(SWIG_RuntimeError, e.what());
  } catch (Swig::DirectorException& e) {
    SWIG_fail;
  } 
}

%{
    #define SWIG_FILE_WITH_INIT

    #include <exception>
    #include <string>
    #include <ostream>
    #include <typeinfo>
    #include "prj_definitions.h"
    #include "pipeline/pipeline_io.h"
    #include "pipeline/pipe_meta.h"
    #include "pipeline/pipeline_data_structures.h"
    #include "pipeline/serialization.h"
    #include "pipeline/load.h"
    #include "generators/generators.h"
    #include "configuration/configuration.h"
    #include "factory/factories.h"
    #include "formatters/formatters.h"
    #include "exceptions/factory_exceptions.h"
    #include "exceptions/pipeline_exceptions.h"
    #include "exceptions/visitor_exceptions.h"
    #include "common/pdl.h"
    #include "common/pdl_visitors.h"
    #include "common/utility_data_structures.h"
%}

namespace std {
class exception {
public:
    exception();
    exception(const exception& rhs);
    virtual ~exception();
    virtual const char *what(void);
};

%template(strlist) std::list<std::string>;
%template(IOKeyVector) std::vector<gestface::IOKey>;
%template(PipeStepDescriptorVector) std::vector<gestface::PipeStepDescriptor*>;

%template(ConfPair) std::pair<std::string, gestface::Configuration>;
%template(ConfMap)  std::map<std::string, gestface::Configuration>;
}

namespace gestface{

// ****** Static Builder constants *********************************************
#define DEFAULT_CONSTRUCTOR "@default"
// -----------------------------------------------------------------------------
    
class SerializablePDLElement;
class PDLElementVisitor;
class PDLLiteral;
class PDLPair;
class PDLRange;
class PDLComposite;


// ****** Exception classes ****************************************************
// Inline declaration
class gestface_exception : public std::exception{

protected:
    std::string what_msg;

public:
    virtual ~gestface_exception() throw();
    gestface_exception(const std::string& _what_msg);

    virtual const char* what() const throw();
};

class factory_exception : public gestface_exception{
public:
    virtual ~factory_exception() throw();
    factory_exception(const std::string& _what_msg);
};

class bad_class : public factory_exception{
public:
    virtual ~bad_class() throw();
    bad_class(const std::string& _what_msg);
};

class bad_parameter : public factory_exception{
public:
    virtual ~bad_parameter() throw();
    bad_parameter(const std::string& _what_msg);
};

class pipeline_exception : public gestface_exception{
private:
    std::string what_msg;

public:
    virtual ~pipeline_exception() throw(){}
    pipeline_exception(const std::string& _what_msg) : gestface_exception(_what_msg) {}
};

class bad_io_mapping : public pipeline_exception{
private:
    std::string what_msg;

public:
    virtual ~bad_io_mapping() throw(){}
    bad_io_mapping(const std::string& _what_msg) : pipeline_exception(_what_msg) {}
};

class bad_computation : public pipeline_exception{
private:
    std::string what_msg;

public:
    virtual ~bad_computation() throw(){}
    bad_computation(const std::string& _what_msg) : pipeline_exception(_what_msg) {}
};

class bad_element : public pipeline_exception{
public:
    virtual ~bad_element() throw(){}
    bad_element(const std::string& _what_msg) : pipeline_exception(_what_msg) {}
};

class bad_visitor : public gestface_exception{
public:
    ~bad_visitor() throw(){}
    bad_visitor(const std::string& _what_msg) : gestface_exception(_what_msg) {}
};

// -----------------------------------------------------------------------------

class Key{
public:
    static const std::string KEY_SEPARATOR;

protected:
    std::string ns;
    std::string key_name;

public:
    virtual ~Key();
    Key();
    Key(const Key& k);
    Key& operator=(const Key& k);

    std::string get_key() const;
    void set_key(const std::string& _ns, const std::string& _key_name);

    virtual bool operator==(const Key& k) const;
    virtual bool operator!=(const Key& k) const;
    virtual bool operator< (const Key& k) const;
};

class IOKey : public Key{
private:
    std::string type;

public:
    virtual ~IOKey();
    IOKey();
    IOKey(const IOKey& k);
    IOKey& operator=(const IOKey& k);

    std::string getType() const;
    IOKey& setType(const std::string& _type);
    const SerializablePDLElement& getAcceptedValues() throw(gestface_exception);
    

    virtual bool operator==(const Key& k) const;
    virtual bool operator!=(const Key& k) const;
    virtual bool operator< (const Key& k) const;
};

%extend IOKey {
    const char* __hash__(){
        return ($self->get_key() + gestface::Key::KEY_SEPARATOR + $self->getType()).c_str();
    }
}

// ****** IOElement interface **************************************************
class IOElement{
public:
    virtual ~IOElement(){}
    virtual boost::any& getElement() const = 0;
    virtual void setElement(boost::any* const element) = 0;
    virtual const IOKey& getIOKey() const = 0;
    virtual IOElement& setIOKey(const IOKey& k) = 0;
    virtual IOElement& setIOKey(const char* _ns, const char* _key_name) = 0;
    virtual IOElement& setIOKey(const std::string& _ns, std::string& _key_name) = 0;
    virtual IOElement& setIOKey(const std::string& _ns, std::string& _key_name, const std::string type) = 0;

    virtual bool operator==(const IOElement& _element) const = 0;
    virtual bool operator!=(const IOElement& _element) const = 0;
};
// -----------------------------------------------------------------------------

// ****** Generator interface definition ***************************************
class Generator{
public:
    virtual ~Generator(){}
    virtual IOElement* generate(void) = 0;
    virtual IOElement* generate(const IOKey& key) = 0;

    virtual Generator& set_key(const IOKey& k) = 0;
    virtual Generator& set_key(const std::string& ns, const std::string& key_name) = 0;
    virtual const IOKey& get_key() const = 0;

    virtual IOElement* last_generated() const = 0;

    virtual bool operator==(const Generator& g) const = 0;
    virtual bool operator!=(const Generator& g) const = 0;
};
// -----------------------------------------------------------------------------

// ****** Configuration classes ************************************************
class ConfigurationTemplate{

protected:
    typedef std::vector<IOKey> set_t;
    set_t params_set;
public:
    ~ConfigurationTemplate();
    ConfigurationTemplate();
    ConfigurationTemplate(const ConfigurationTemplate& ct);
    ConfigurationTemplate& operator=(const ConfigurationTemplate& ct);

    ConfigurationTemplate& add(const IOKey& key);
    const IOKey& param_at(int idx) const throw(std::out_of_range);
    bool contains(const IOKey& key) const;
    size_t parameters_num() const;
};

class Configuration{
protected:
    ConfigurationTemplate ct;
    typedef std::map<IOKey, boost::any*> params_map_t;
    params_map_t params;
public:
    virtual ~Configuration();
    Configuration();
    Configuration(const Configuration& c);
    Configuration& operator=(const Configuration& c);

    Configuration(const ConfigurationTemplate& ct);

    Configuration& set_template(const ConfigurationTemplate& ct);
    const ConfigurationTemplate& get_template() const;

    template<typename T>
    Configuration& set_parameter(const IOKey& k, const T& value);

    template<typename T>
    T get_parameter(const IOKey& k) const throw(bad_parameter);
};

%template(set_int_parameter) Configuration::set_parameter<int>;
%template(set_long_parameter) Configuration::set_parameter<long>;
%template(set_double_parameter) Configuration::set_parameter<double>;
%template(set_float_parameter) Configuration::set_parameter<float>;
%template(set_string_parameter) Configuration::set_parameter<std::string>;
%template(set_generator_ptr_parameter) Configuration::set_parameter<Generator*>;
%template(set_IOKey_parameter) Configuration::set_parameter<IOKey>;

%template(get_int_parameter) Configuration::get_parameter<int>;
%template(get_long_parameter) Configuration::get_parameter<long>;
%template(get_double_parameter) Configuration::get_parameter<double>;
%template(get_float_parameter) Configuration::get_parameter<float>;
%template(get_string_parameter) Configuration::get_parameter<std::string>;
%template(get_generator_ptr_parameter) Configuration::get_parameter<Generator*>;
%template(get_IOKey_parameter) Configuration::get_parameter<IOKey>;

// -----------------------------------------------------------------------------

// ****** Formatter interface definition ***************************************
class Formatter{
public:
    typedef IOElement format_t;

    virtual ~Formatter(){}

    virtual Formatter& format() const = 0;
    virtual Formatter& format(const IOElement& el) const = 0;

    virtual Formatter& set_key(const IOKey& k) = 0;
    virtual const IOKey& get_key() const = 0;

    virtual bool operator==(const Formatter& g) const = 0;
    virtual bool operator!=(const Formatter& g) const = 0;
};
// -----------------------------------------------------------------------------

// ****** Pipeline elements ****************************************************
class PipeStepComputation{
public:
    typedef pipe_input_t input_t;
    typedef pipe_output_t output_t;
    typedef pipe_criteria_t criteria_t;

    virtual ~PipeStepComputation(){};
    virtual bool doOperation(const std::list<input_t>& inputs,
                             const std::list<criteria_t>& operationCriteria,
                             std::list<output_t>& outputs) = 0;

    virtual const std::vector<IOKey>& getInputKeysList() const = 0;
    virtual const std::vector<IOKey>& getCriteriaKeysList() const = 0;
    virtual const std::vector<IOKey>& getOutputKeysList() const = 0;
};
// -----------------------------------------------------------------------------

class PipeStep{

public:
    typedef pipe_input_t input_t;
    typedef pipe_output_t output_t;
    typedef pipe_criteria_t criteria_t;

private:
    std::list<Generator*>* input_generators;
    std::list<Generator*>* output_generators;
    std::list<Generator*>* criteria_generators;

    std::map<IOKey, input_t>* inputs;
    std::map<IOKey, output_t>* outputs;
    std::map<IOKey, criteria_t>* criteria;

    std::list<Formatter*>* output_formatters;

    PipeStepComputation* computation;

public:
    ~PipeStep();
    PipeStep();
    PipeStep(const PipeStep& ps);
    PipeStep& operator=(const PipeStep& ps);

    virtual bool execute() throw(bad_computation, bad_io_mapping, gestface_exception);

    PipeStep& add_input(input_t _input);
    PipeStep& add_criteria(input_t _criteria);
    PipeStep& add_output(input_t _output);

    PipeStep& add_input_generator(Generator* gen);
    PipeStep& add_criteria_generator(Generator* gen);
    PipeStep& add_output_generator(Generator* gen);

    PipeStep& add_output_formatter(Formatter* formatter);

    PipeStep& set_computation(PipeStepComputation* _computation);
};
// -----------------------------------------------------------------------------

// ****** Pipeline definition **************************************************
class Pipeline : public PipeStepComputation{
public:
    typedef pipe_input_t input_t;
    typedef pipe_output_t output_t;
    typedef pipe_criteria_t criteria_t;

private:
    std::vector<PipeStep*>* pipe_steps;

public:
    ~Pipeline();
    Pipeline();
    Pipeline(const Pipeline& p);
    Pipeline& operator=(const Pipeline& p);

    virtual bool doOperation(const std::list<input_t>& inputs,
                             const std::list<criteria_t>& operationCriteria,
                             std::list<output_t>& outputs) throw(bad_io_mapping);

    const std::vector<IOKey>& getInputKeysList() const;
    const std::vector<IOKey>& getCriteriaKeysList() const;
    const std::vector<IOKey>& getOutputKeysList() const;

    Pipeline& add_pipe_step(PipeStep* pipe_step);
};
// -----------------------------------------------------------------------------

// ****** factory interface definition *****************************************
template<typename FactorizedT>
class Factory{
public:
    typedef FactorizedT factorized_t;

    virtual ~Factory(){}
    virtual FactorizedT* build() const = 0;
};
// -----------------------------------------------------------------------------

// ****** Static generator builder definition **********************************
%newobject FactoriesPool::build;

template<typename BuildedT>
class FactoriesPool{
private:
    FactoriesPool(){}
    FactoriesPool(const FactoriesPool& b);
    FactoriesPool& operator=(const FactoriesPool& b);

    std::map< std::string, Factory<BuildedT>* > factory_map;
    static FactoriesPool<BuildedT>* singleton_instance;
public:
    ~FactoriesPool();

    static FactoriesPool<BuildedT>* get_instance();
    static void free_instance();
    const ConfigurationTemplate& get_configuration_template(const std::string& class_name) throw(bad_class);
    BuildedT* build( const std::string& class_name,
                            const Configuration& conf = Configuration() ) throw(bad_parameter, bad_class);
    void list_all_classes( std::list<std::string>& out_list );
};

%template( GeneratorFactoriesPool )   FactoriesPool<Generator>;
%template( ComputationFactoriesPool ) FactoriesPool<PipeStepComputation>;
%template( FormatterFactoriesPool )   FactoriesPool<Formatter>;
// -----------------------------------------------------------------------------


// ****** Abstract PDLElements definitions *************************************
class PDLElement{
public:
    virtual ~PDLElement(){};
    virtual bool validate(double _value) const = 0;
    virtual bool validate(const std::string& _value) const = 0;
    virtual PDLElement* clone() const = 0;
};

class SerializablePDLElement: public PDLElement{
public:
    virtual ~SerializablePDLElement(){};
    virtual bool validate(double _value) const = 0;
    virtual bool validate(const std::string& _value) const = 0;
    virtual const SerializablePDLElement& serialize(PDLElementVisitor& vis) const = 0;
    virtual PDLElement* clone() const = 0;
    virtual SerializablePDLElement* cloneSerializable() const = 0;
};
// -----------------------------------------------------------------------------

// ****** PDLElementVisitor definition *****************************************
%feature("director") PDLElementVisitor;
class PDLElementVisitor{
public:
    virtual ~PDLElementVisitor(){};
    virtual double visitPDLLiteral(const PDLLiteral& l) throw(bad_visitor) = 0;
    virtual void visitPDLPair(const PDLPair& p) throw(bad_visitor) = 0;
    virtual double visitPDLRange(const PDLRange& range) throw(bad_visitor) = 0;
    virtual void visitPDLComposite(const PDLComposite& composite) throw(bad_visitor) = 0;
};
// -----------------------------------------------------------------------------

// ****** PDLLiteral definition ************************************************
class PDLLiteral : public SerializablePDLElement{    
public:
    ~PDLLiteral();
    PDLLiteral();
    PDLLiteral(double _value);
    PDLLiteral(const PDLLiteral& literal);
    const PDLLiteral& operator=(const PDLLiteral& literal);

    bool validate(double _value) const ;
    bool validate(const std::string& _value) const ;
    const SerializablePDLElement& serialize(PDLElementVisitor& vis) const;
    PDLElement* clone() const;
    SerializablePDLElement* cloneSerializable() const;
    double get_value() const;
};
// -----------------------------------------------------------------------------

// ****** PDLDict definition ***************************************************
class PDLPair : public SerializablePDLElement{
public:
    ~PDLPair();
    PDLPair();
    PDLPair(const std::string& _label, int _value);
    PDLPair(const PDLPair& element);
    const PDLPair& operator=(const PDLPair& element);

    bool validate(double label) const ;
    bool validate(const std::string& label) const ;
    const SerializablePDLElement& serialize(PDLElementVisitor& vis) const;
    PDLElement* clone() const;
    SerializablePDLElement* cloneSerializable() const;
    double get_value() const;
    std::string get_label() const;
};
// -----------------------------------------------------------------------------

// ****** PDLRange definition **************************************************
class PDLRange : public SerializablePDLElement{
private:
    double from, to, scale;
    double step;

public:
    ~PDLRange();
    PDLRange();
    PDLRange(double _from, double _to, double _step = 1);
    PDLRange(const PDLRange& element);
    const PDLRange& operator=(const PDLRange& element);

    bool validate(double _value) const ;
    bool validate(const std::string& label) const ;
    const SerializablePDLElement& serialize(PDLElementVisitor& vis) const;
    PDLElement* clone() const;
    SerializablePDLElement* cloneSerializable() const;
    
    double get_from() const;
    double get_to() const;
    double get_step() const;
    double get_scale() const;
};
// -----------------------------------------------------------------------------

// ****** PDLComposite definition **********************************************
class PDLCompositeIterator;

class PDLComposite : public SerializablePDLElement{
public:
    typedef PDLCompositeIterator iterator;
    typedef PDLCompositeConstIterator const_iterator;

public:
    ~PDLComposite();
    PDLComposite();
    PDLComposite(const PDLComposite& element);
    const PDLComposite& operator=(const PDLComposite& element);

    PDLComposite& add_element(PDLElement& element);

    bool validate(double _value) const ;
    bool validate(const std::string& label) const ;
    const SerializablePDLElement& serialize(PDLElementVisitor& vis) const;
    PDLElement* clone() const;
    SerializablePDLElement* cloneSerializable() const;
    
    iterator begin();
    iterator end();
};
// -----------------------------------------------------------------------------

// ****** PDLCompositeIterator *************************************************
class PDLCompositeIterator{
public:
    typedef PDLElement iter_t;
public:
    PDLCompositeIterator(PDLComposite* _composite);
    
    PDLElement& operator*() const;
    PDLElement* operator->() const;
    
    PDLElement* next();
    SerializablePDLElement* nextSerializable();
    bool has_next() const;

    bool operator==(const PDLCompositeIterator&) const;
    bool operator!=(const PDLCompositeIterator&) const;
};
// -----------------------------------------------------------------------------

/*
// ****** QtGuiPDLVisitor ******************************************************
class QtGuiPDLVisitor : public PDLElementVisitor{
private:
    QLayout* layout;
public:
    ~QtGuiPDLVisitor();
    QtGuiPDLVisitor();
    QtGuiPDLVisitor(const QtGuiPDLVisitor& visitor);
    QtGuiPDLVisitor(QLayout* _layout);
    const QtGuiPDLVisitor& operator=(const QtGuiPDLVisitor& visitor);
    
    void set_layout(QLayout* _layout);
    void set_layout_address(long _layout_address);
    double visitPDLRange(const PDLRange& range) throw(bad_visitor);
    void   visitPDLComposite(const PDLComposite& composite) throw(bad_visitor);
};
// -----------------------------------------------------------------------------
*/


// ###### DESCRIPTORS ##########################################################
    
class PDSVisitor;

// ****** PipeStepDescriptor definition ****************************************    
%newobject PipeStepDescriptor::clone;
%newobject PipeStepDescriptor::ref_clone;
class PipeStepDescriptor{    
public:
    ~PipeStepDescriptor();
    PipeStepDescriptor();
    PipeStepDescriptor(const PipeStepDescriptor& d);
    PipeStepDescriptor(const std::string& id);
    const PipeStepDescriptor& operator=(const PipeStepDescriptor& d);
    
    // *** Getters
    
    const std::string&                           get_id() const;
    virtual void                                 get_computation(PDSVisitor& v) const = 0;
    virtual const std::string&                   get_computation_name() const = 0;
    const std::pair<std::string, Configuration>& get_in_gen(const IOKey& k) const;
    const Configuration&                         get_in_conf(const IOKey& k, const std::string& gen) const;
    const std::pair<std::string, Configuration>& get_out_gen(const IOKey& k) const;
    const Configuration&                         get_out_conf(const IOKey& k, const std::string& gen) const;
    const std::map<std::string, Configuration>&  get_formatters(const IOKey& k) const;
    const Configuration&                         get_formatter_conf(const IOKey& k, const std::string& form) const;
    const std::string&                           get_criteria(const IOKey& k) const;
    
    // *** Setters
    
    virtual PipeStepDescriptor& set_computation(const PDSVisitor& v) = 0;
    PipeStepDescriptor& set_id(const std::string& id);
    PipeStepDescriptor& set_in_gen(const IOKey& k, const std::pair<std::string, Configuration>& gen);
    PipeStepDescriptor& set_in_conf(const IOKey& k, const std::string& gen, const Configuration& conf);
    PipeStepDescriptor& set_out_gen(const IOKey& k, const std::pair<std::string, Configuration>& gen);
    PipeStepDescriptor& set_out_conf(const IOKey& k, const std::string& gen, const Configuration& conf);
    PipeStepDescriptor& set_formatters(const IOKey& k, const std::map<std::string, Configuration>& formatter);
    PipeStepDescriptor& set_formatter_conf(const IOKey& k, const std::string& form, const Configuration& conf);
    PipeStepDescriptor& set_criteria(const IOKey& k, const std::string& value);
    
    virtual PipeStepDescriptor* clone() const = 0;
};
// -----------------------------------------------------------------------------
// _____________________________________________________________________________


// _____________________________________________________________________________


// ###### DESCRIPTOR CONSUMERS #################################################

// ****** PipeStepDescrConsumer definition *************************************
%feature("director") PipeStepDescrConsumer;
class PipeStepDescrConsumer{
public:
    virtual ~PipeStepDescrConsumer(){}
    virtual void consume(const PipeStepDescriptor& d) = 0;
};
// -----------------------------------------------------------------------------

// ****** AbsPipeStepDescrConsumer definition **********************************
%feature("director") AbsPipeStepDescrConsumer;
class AbsPipeStepDescrConsumer : public PipeStepDescrConsumer{
public:    
    virtual ~AbsPipeStepDescrConsumer();
    AbsPipeStepDescrConsumer();
    AbsPipeStepDescrConsumer(const AbsPipeStepDescrConsumer& c);
    const AbsPipeStepDescrConsumer& operator=(const AbsPipeStepDescrConsumer& c);
    virtual void consume(const PipeStepDescriptor& d) = 0;
};
// -----------------------------------------------------------------------------

// ****** PipeStepXMLSerializer definition *************************************
class PipeStepXMLSerializer : public AbsPipeStepDescrConsumer{
public:
    ~PipeStepXMLSerializer();    
    void consume(const PipeStepDescriptor& d);    
    bool serialize(const std::string& filename);    
    static PipeStepXMLSerializer* get_instance(const std::string& s = "LS");
    static void free_instance();
private:
    PipeStepXMLSerializer();
    PipeStepXMLSerializer(const PipeStepXMLSerializer& psx);
    PipeStepXMLSerializer(const std::string& s);
    PipeStepXMLSerializer& operator=(const PipeStepXMLSerializer& psx);
};
// -----------------------------------------------------------------------------

// _____________________________________________________________________________


// ###### DESCRIPTOR BUILDERS ##################################################

// ****** PipeStepDescrBuilder definition **************************************
%feature("director") PipeStepDescrBuilder;
class PipeStepDescrBuilder{
public:
    virtual ~PipeStepDescrBuilder(){}
    virtual void build(std::vector<PipeStepDescriptor*>&) = 0;
};
// -----------------------------------------------------------------------------

// ****** AbsPipeStepDescrBuilder definition **********************************
%feature("director") AbsPipeStepDescrBuilder;
class AbsPipeStepDescrBuilder : public PipeStepDescrBuilder{
public:
    virtual ~AbsPipeStepDescrBuilder(){}
    virtual void build(std::vector<PipeStepDescriptor*>&) = 0;
};
// -----------------------------------------------------------------------------

// ****** XMLPipeStepDescriptorBuilder definition ******************************

class XMLPipeStepDescriptorBuilder : public AbsPipeStepDescrBuilder{
public:
    ~XMLPipeStepDescriptorBuilder();
    
    virtual void build(std::vector<PipeStepDescriptor*>&);
    
    static XMLPipeStepDescriptorBuilder* get_instance(const std::string& _filename, const std::string& s = "LS");
    static void free_instance();
private:
    XMLPipeStepDescriptorBuilder();
    XMLPipeStepDescriptorBuilder(const XMLPipeStepDescriptorBuilder&);
    XMLPipeStepDescriptorBuilder(const std::string& _filename, const std::string& s);
    XMLPipeStepDescriptorBuilder& operator= (const XMLPipeStepDescriptorBuilder&);
};

// -----------------------------------------------------------------------------

// _____________________________________________________________________________




// ###### VISITORS #############################################################
class PipelineDescriptor;
class SingleStepDescriptor;

// ****** PDSVisitor definition ************************************************
class PDSVisitor{
public:
    virtual ~PDSVisitor(){}

    virtual void get_pipeline(const PipelineDescriptor& d) = 0;
    virtual void get_single_step(const SingleStepDescriptor& d) = 0;
    
    virtual void set_pipeline(PipelineDescriptor& d) const = 0;
    virtual void set_single_step(SingleStepDescriptor& d) const = 0;
};    
// -----------------------------------------------------------------------------

// ****** AbsPDSVisitor definition *********************************************
class AbsPDSVisitor : public PDSVisitor{
public:
    virtual ~AbsPDSVisitor(){}

    virtual void get_pipeline(const PipelineDescriptor& d) = 0;
    virtual void get_single_step(const SingleStepDescriptor& d) = 0;
    
    virtual void set_pipeline(PipelineDescriptor& d) const = 0;
    virtual void set_single_step(SingleStepDescriptor& d) const = 0;
};    
// -----------------------------------------------------------------------------

// ****** GenericPDSVisitor definition *****************************************
%newobject GenericPDSVisitor::get_computation;
class GenericPDSVisitor : public AbsPDSVisitor{
public:
    void get_pipeline(const PipelineDescriptor& d);
    void get_single_step(const SingleStepDescriptor& d);
    
    void set_pipeline(PipelineDescriptor& d) const;
    void set_single_step(SingleStepDescriptor& d) const;
    
    void set_computation_name(const std::string& name);
    void set_descr_builder(PipeStepDescrBuilder* builder);
    
    PipeStepComputation* get_computation() const;
    
};    
// -----------------------------------------------------------------------------

// _____________________________________________________________________________



// ###### DESCRIPTORS ##########################################################

// ****** PipelineDescriptor definition ****************************************
class PipelineDescriptor : public PipeStepDescriptor{
public:
    PipelineDescriptor();
    PipelineDescriptor(const std::string& id);
    PipelineDescriptor(const PipelineDescriptor& p);
    ~PipelineDescriptor();
    
    PipeStepDescriptor& add_step(const PipeStepDescriptor& step);
    
    void get_computation(PDSVisitor& v) const;
    const std::string& get_computation_name() const;
    std::vector<PipeStepDescriptor*>& get_computation_steps();
    PipeStepDescriptor& set_computation(const PDSVisitor& v);
    PipeStepDescriptor& set_computation(const std::vector<PipeStepDescriptor*>& _computation);
    
    PipeStepDescriptor* clone() const;
};

%extend PipelineDescriptor{
    static PipelineDescriptor* castTo(PipeStepDescriptor* p){
        return dynamic_cast<gestface::PipelineDescriptor*>(p);
    }
}
// -----------------------------------------------------------------------------

// ****** SingleStepDescriptor definition **************************************
class SingleStepDescriptor : public PipeStepDescriptor{
public:
    SingleStepDescriptor();
    SingleStepDescriptor(const std::string& id);
    void get_computation(PDSVisitor& v) const;
    const std::string& get_computation_name() const;
    PipeStepDescriptor& set_computation(const PDSVisitor& v);
    PipeStepDescriptor& set_computation(const std::string& str);
    
    PipeStepDescriptor* clone() const;
};

%extend SingleStepDescriptor{
    static SingleStepDescriptor* castTo(PipeStepDescriptor* p){
        return dynamic_cast<gestface::SingleStepDescriptor*>(p);
    }
}
// -----------------------------------------------------------------------------

// _____________________________________________________________________________

// ****** PipelineLoader definition ********************************************
class PipelineLoader{
public:
    PipelineLoader();
    
    PipelineLoader& set_descr_builder(PipeStepDescrBuilder* builder);
    PipelineLoader& set_descr_consumer(PipeStepDescrConsumer* consumer);
    
    PipelineLoader& load() const;
};
// -----------------------------------------------------------------------------
} 